﻿#include "FITKAbaqusHDF5AdaptorPredefinedField.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractPredefinedField.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaPredefinedFieldVelocity.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaPredefinedFieldTemperature.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepManager.h"

namespace IO
{
    QString FITKAbaqusHDF5AdaptorPredefinedField::getAdaptorClass()
    {
        return "FITKAbaqusHDF5AdaptorPredefinedField";
    }


    void FITKAbaqusHDF5AdaptorPredefinedField::setStepManager(Interface::FITKAbaStepManager* stepManager)
    {
        _stepManager = stepManager;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::adaptR()
    {
        auto pf = dynamic_cast<Interface::FITKAbaAbstractPredefinedField*>(_dataObj);
        if (!_reader || !pf || !_h5Group || !_stepManager) return false;
        bool isR = true;
        isR &= readPredefinedField(pf, *_h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::adaptW()
    {
        auto pf = dynamic_cast<Interface::FITKAbaAbstractPredefinedField*>(_dataObj);
        if (!_writer || !pf || !_h5Group || !_stepManager) return false;
        bool isW = true;
        isW &= writePredefinedField(pf, *_h5Group);
        return isW;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::readPredefinedField(Interface::FITKAbaAbstractPredefinedField* pf, H5::Group& h5Group)
    {
        if (!pf) return false;
        bool isValid = false;
        bool isR = true;

        if (!FITKInterfaceHDF5AdaptorBoundaryLocation::readBoundaryLocation(pf, h5Group)) return false;
        bool bActiveState = readBoolAttribute(h5Group, "ActiveState");
        pf->setActiveState(bActiveState);

        auto ePreDefinedType = pf->getPreDefinedType();
        if (ePreDefinedType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Temperature)
        {
            isR &= readPredefinedFieldTemperature(pf, h5Group);
        }
        else if (ePreDefinedType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Velocity)
        {
            isR &= readPredefinedFieldVelocity(pf, h5Group);
        }
        else
        {
            return false;
        }

        return isR;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::writePredefinedField(Interface::FITKAbaAbstractPredefinedField* pf, H5::Group& h5Group)
    {
        if (!pf) return false;
        bool isValid = false;
        bool isW = true;
        std::string groupName = createParentAttribute(pf, h5Group);
        if (groupName.empty())return false;
        _h5CreateGroup = h5Group.createGroup(groupName);

        if (!FITKInterfaceHDF5AdaptorBoundaryLocation::writeBoundaryLocation(pf, h5Group)) return false;

        auto ePreDefinedType = pf->getPreDefinedType();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType> fitkTypeTrafer;
        auto sPreDefinedType = fitkTypeTrafer.toStrting(ePreDefinedType, isValid);
        if (!isValid) return false;
        writeStrAttribute(_h5CreateGroup, "PreDefinedType", sPreDefinedType.toStdString());

        bool bActiveState = pf->getActiveState();
        writeBoolAttribute(_h5CreateGroup, "ActiveState", &bActiveState);

        if (ePreDefinedType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Temperature)
        {
            isW &= writePredefinedFieldTemperature(pf, _h5CreateGroup);
        }
        else if (ePreDefinedType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Velocity)
        {
            isW &= writePredefinedFieldVelocity(pf, _h5CreateGroup);
        }
        else
        {
            return false;
        }

        return isW;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::readPredefinedFieldTemperature(Interface::FITKAbaAbstractPredefinedField * pf, H5::Group & h5Group)
    {
        auto fieldTemperature = dynamic_cast<Interface::FITKAbaPredefinedFieldTemperature*>(pf);
        if (!fieldTemperature)  return false;
        bool isValid = false;
        auto eDistribution = fieldTemperature->getDistribution();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaPredefinedFieldTemperature::TemperatureDistribution> fitkTypeTrafer;
        auto sDistribution = fitkTypeTrafer.toStrting(eDistribution, isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "Distribution", sDistribution.toStdString());

        //写出不同分析步的输出
        for (int i = 1; i < _stepManager->getDataCount(); ++i)
        {
            auto step = _stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();

            if (!h5Group.nameExists(std::to_string(stepID))) return false;
            auto childGroup = h5Group.openGroup(std::to_string(stepID));
            //base FITKAbaStepRelatedDataObject
            int createdStep = readIntAttribute(childGroup, "CreatedStep");
            fieldTemperature->setCreatedStep(createdStep);
            int deactiveStep = readIntAttribute(childGroup, "DeactiveStep");
            fieldTemperature->setDeactiveStep(deactiveStep);
            double magnitude = readDoubleAttribute(childGroup, "Magnitude");
            fieldTemperature->setMagnitude(magnitude, stepID);
            int amplitudeId = readIntAttribute(childGroup, "AmplitudeId");
            fieldTemperature->setAmplitudeId(amplitudeId, stepID);

            auto sStateInStep = readStrAttribute(childGroup, "StateInStep");
            //枚举转换字符
            Core::FITKEnumTransfer<Interface::FITKAbaStepEnum::StateInStep> fitkSISTypeTrafer;
            auto eStateInStep = fitkSISTypeTrafer.fromString(QString::fromStdString(sStateInStep), isValid);
            if (!isValid) return false;
            fieldTemperature->setStateInStep(eStateInStep, stepID);
        }

        return true;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::writePredefinedFieldTemperature(Interface::FITKAbaAbstractPredefinedField * pf, H5::Group & h5Group)
    {
        auto fieldTemperature = dynamic_cast<Interface::FITKAbaPredefinedFieldTemperature*>(pf);
        if (!fieldTemperature)  return false;
        bool isValid = false;
        auto eDistribution = fieldTemperature->getDistribution();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaPredefinedFieldTemperature::TemperatureDistribution> fitkTypeTrafer;
        auto sDistribution = fitkTypeTrafer.toStrting(eDistribution, isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "Distribution", sDistribution.toStdString());

        //写出不同分析步的输出
        for (int i = 1; i < _stepManager->getDataCount(); ++i)
        {
            auto step = _stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();
            auto childGroup = h5Group.createGroup(std::to_string(stepID));
            //base FITKAbaStepRelatedDataObject
            int createdStep = fieldTemperature->getCreatedStep();
            writeIntAttribute(childGroup, "CreatedStep", &createdStep);
            int deactiveStep = fieldTemperature->getDeactiveStep();
            writeIntAttribute(childGroup, "DeactiveStep", &deactiveStep);
            double magnitude = fieldTemperature->getMagnitude(i);
            writeDoubleAttribute(childGroup, "Magnitude", &magnitude);
            int amplitudeId = fieldTemperature->getAmplitudeId(i);
            writeIntAttribute(childGroup, "AmplitudeId", &amplitudeId);

            auto eStateInStep = fieldTemperature->getStateInStep(i);
            //枚举转换字符
            Core::FITKEnumTransfer<Interface::FITKAbaStepEnum::StateInStep> fitkSISTypeTrafer;
            auto sStateInStep = fitkSISTypeTrafer.toStrting(eStateInStep, isValid);
            if (!isValid) return false;
            writeStrAttribute(childGroup, "StateInStep", sStateInStep.toStdString());
        }

        return true;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::readPredefinedFieldVelocity(Interface::FITKAbaAbstractPredefinedField * pf, H5::Group & h5Group)
    {
        auto fieldVelocity = dynamic_cast<Interface::FITKAbaPredefinedFieldVelocity*>(pf);
        if (!fieldVelocity)  return false;
        bool isValid = false;
        auto sDefinition = readStrAttribute(h5Group, "Definition");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition> fitkTypeTrafer;
        auto eDefinition = fitkTypeTrafer.fromString(QString::fromStdString(sDefinition), isValid);
        if (!isValid) return false;
        fieldVelocity->setDefinition(eDefinition);

        double V1 = readDoubleAttribute(h5Group, "V1");
        fieldVelocity->setV1(V1);
        double V2 = readDoubleAttribute(h5Group, "V2");
        fieldVelocity->setV2(V2);
        double V3 = readDoubleAttribute(h5Group, "V3");
        fieldVelocity->setV3(V3);

        double AngularVelocity = readDoubleAttribute(h5Group, "AngularVelocity");
        fieldVelocity->setAngularVelocity(AngularVelocity);
        auto AxisPoint1 = fieldVelocity->getAxisPoint1();

        if (h5Group.attrExists("AxisPoint1"))
        {
            H5::Attribute att = h5Group.openAttribute("AxisPoint1");
            std::array<double, 3> buf;
            att.read(H5::PredType::NATIVE_DOUBLE, &buf);
            fieldVelocity->setAxisPoint1(buf);
        }

        if (h5Group.attrExists("AxisPoint2"))
        {
            H5::Attribute att = h5Group.openAttribute("AxisPoint2");
            std::array<double, 3> buf;
            att.read(H5::PredType::NATIVE_DOUBLE, &buf);
            fieldVelocity->setAxisPoint2(buf);
        }

        //写出不同分析步的输出
        for (int i = 1; i < _stepManager->getDataCount(); ++i)
        {
            auto step = _stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();

            if (!h5Group.nameExists(std::to_string(stepID))) return false;
            auto childH5Group = h5Group.openGroup(std::to_string(stepID));

            //base FITKAbaStepRelatedDataObject
            int CreatedStep = readIntAttribute(childH5Group, "CreatedStep");
            fieldVelocity->setCreatedStep(CreatedStep);

            int DeactiveStep = readIntAttribute(childH5Group, "DeactiveStep");
            fieldVelocity->setDeactiveStep(DeactiveStep);
        }
        return true;
    }

    bool FITKAbaqusHDF5AdaptorPredefinedField::writePredefinedFieldVelocity(Interface::FITKAbaAbstractPredefinedField * pf, H5::Group & h5Group)
    {
        auto fieldVelocity = dynamic_cast<Interface::FITKAbaPredefinedFieldVelocity*>(pf);
        if (!fieldVelocity)  return false;
        bool isValid = false;
        auto eDefinition = fieldVelocity->getDefinition();
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition> fitkTypeTrafer;
        auto sDefinition = fitkTypeTrafer.toStrting(eDefinition, isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "Definition", sDefinition.toStdString());

        double V1 = fieldVelocity->getV1();
        writeDoubleAttribute(h5Group, "V1", &V1);
        double V2 = fieldVelocity->getV2();
        writeDoubleAttribute(h5Group, "V2", &V2);
        double V3 = fieldVelocity->getV3();
        writeDoubleAttribute(h5Group, "V3", &V3);
        double AngularVelocity = fieldVelocity->getAngularVelocity();
        writeDoubleAttribute(h5Group, "AngularVelocity", &AngularVelocity);
        auto AxisPoint1 = fieldVelocity->getAxisPoint1();
        writeBoolAttribute(h5Group, "AxisPoint1", &AxisPoint1, 1, 3);
        auto AxisPoint2 = fieldVelocity->getAxisPoint2();
        writeBoolAttribute(h5Group, "AxisPoint2", &AxisPoint2, 1, 3);
        //写出不同分析步的输出
        for (int i = 1; i < _stepManager->getDataCount(); ++i)
        {
            auto step = _stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();

            auto childGroup = h5Group.createGroup(std::to_string(stepID));
            //base FITKAbaStepRelatedDataObject
            int createdStep = fieldVelocity->getCreatedStep();
            writeIntAttribute(childGroup, "CreatedStep", &createdStep);
            int deactiveStep = fieldVelocity->getDeactiveStep();
            writeIntAttribute(childGroup, "DeactiveStep", &deactiveStep);
        }
        return true;
    }

}


